﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Text.RegularExpressions;
using Clipping.Infrastructure.Models;

namespace Clipping.Utils.SearchEngines
{
    public class SougouNews:ISearchEngine 
    {
        private Encoding _encoding = Encoding.GetEncoding("gb2312");
        private Encoding _contentEncoding =Encoding.GetEncoding("gb2312");
        public void Parse(Uri url, string html, out List<News> news, out string nextPageUrl)
        {
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
            if (news != null)
            {
                foreach (var n in news)
                {
                    if (!string.IsNullOrEmpty(n.SameNewsUrl))
                        n.SameNewsUrl = constructAbsoluteUrl(url, n.SameNewsUrl).OriginalString;
                }
            }
        }

        public Uri ConstructUrl(SearchObject searchObj)
        {
            return constructUrl(searchObj);
        }

        public void Search(Infrastructure.Models.SearchObject searchObj, IHtmlDownload downloader, out List<Infrastructure.Models.News> news, out string nextPageUrl)
        {
            var url = constructUrl(searchObj);
            string html = downloader.GetHtml(url);
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
            if (news != null)
            {
                foreach (var n in news)
                {
                    if (!string.IsNullOrEmpty(n.SameNewsUrl))
                        n.SameNewsUrl = constructAbsoluteUrl(url, n.SameNewsUrl).OriginalString;
                }
            }
        }



        #region 私有方法


        private Uri constructUrl(Infrastructure.Models.SearchObject searchObj)
        {
            if (searchObj.SearchType == Infrastructure.Models.SearchType.SearchInTitle)
            {
                return new Uri(string.Format("http://news.sogou.com/news?query={0}&mode=2", HttpUtility.UrlEncode(searchObj.Keyword, this._encoding)));
            }
            else
            {
                return new Uri(string.Format("http://news.sogou.com/news?query={0}&mode=1", HttpUtility.UrlEncode(searchObj.Keyword, this._encoding)));
            }
        }

        private Uri constructAbsoluteUrl(Uri baseUri, string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                return null;
            }
            else if (url.ToLower().StartsWith("?query"))
            {
                string urlStr = "http://news.sogou.com/news" + url;
                return new Uri(urlStr);
            }
            else
                return UriHelper.ConstructAbsoluteUrl(baseUri, url);
        }

        private void parse(string html, out List<Infrastructure.Models.News> news, out string nextPageUrl)
        {
            news = new List<News>();
            nextPageUrl = null;
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var liNav = doc.CreateNavigator();

            var divSearchResult = liNav.Select("//div[@class='rb']");

            while (divSearchResult.MoveNext())
            {
                News n = new News();

                var li = divSearchResult.Current;
                //取标题和链接
                var link = li.SelectSingleNode("descendant::h3/a");
                if (link != null)
                {
                    string title = removeHtmlComments(link.Value);
                    n.Title = System.Web.HttpUtility.HtmlDecode(title);
                    n.Url = link.GetAttribute("href", "");
                }

                //取媒体和时间
                var mediaAndDtNode = li.SelectSingleNode("descendant::h3/cite");
                if (mediaAndDtNode != null)
                {
                    string mediaAndDt = removeHtmlComments(mediaAndDtNode.Value);
                    if (!string.IsNullOrEmpty(mediaAndDt))
                    {
                        mediaAndDt = System.Web.HttpUtility.HtmlDecode(mediaAndDt);
                        mediaAndDt = mediaAndDt.Trim();
                        var match = Regex.Match(mediaAndDt, @"\s");
                        if (match.Success)
                        {
                            int spaceIndex = match.Index;
                            if (spaceIndex > 0)
                            {
                                n.Media = mediaAndDt.Substring(0, spaceIndex);
                                n.PubDate = mediaAndDt.Substring(spaceIndex + 1);
                            }
                        }
                    }
                }
                //取摘要和相同新闻链接
                var summaryAndSameNewsNode = li.SelectSingleNode("descendant::div[@class='ft']");
                if (summaryAndSameNewsNode != null)
                {
                    string summary = summaryAndSameNewsNode.Value;
                    var sameNewsNode = summaryAndSameNewsNode.SelectSingleNode("a[@id='news_similar']");
                    if (sameNewsNode != null)
                    {
                        string sameNewsTitle = sameNewsNode.Value;
                        string sameNewsUrl = sameNewsNode.GetAttribute("href", "");

                        Match m = Regex.Match(sameNewsTitle, @"(\d+)\s*条相同新闻");
                       if (m.Success)
                       {
                           n.SameNewsCount = int.Parse(m.Groups[1].Value);
                       }

                       
                        summary = summary.Replace(sameNewsTitle, "");
                        n.SameNewsUrl = System.Web.HttpUtility.HtmlDecode(sameNewsUrl);
                    }
                    summary = removeHtmlComments(summary);
                    summary = System.Web.HttpUtility.HtmlDecode(summary).Trim();

                    n.Summary = summary;
                }
                news.Add(n);

            }
            //取下一页地址
            var nextPageNode = liNav.SelectSingleNode("//a[@id='sogou_next']");
            if (nextPageNode != null && nextPageNode.Value != null && nextPageNode.Value.Contains("下一页"))
            {
                nextPageUrl = nextPageNode.GetAttribute("href", "");
                MatchEvaluator me = new MatchEvaluator(regexReplace);//搜狗的搜索结果中，下一页的地址，对中文字符未编码
                nextPageUrl = Regex.Replace(nextPageUrl, @"\?query=([^&]+)", me);
            }
        }

        private string regexReplace(Match m)
        {

            return @"?query=" + HttpUtility.UrlEncode(m.Groups[1].Value, this._encoding);
        }

        private string removeHtmlComments(string html)
        {
            if (string.IsNullOrEmpty(html))
                return html;
            else
            {

                return Regex.Replace(html, @"<!--[\s\S]*?-->", "");
            }

        }
        #endregion

        #region 属性

        public string Name
        {
            get { return "搜狗新闻搜索"; }
        }
        public Encoding ContentEncoding
        {
            get { return _contentEncoding; }
        }
        #endregion


        
    }
}
